package SweetPea::Seeds;

use warnings;
use strict;
use Carp;
use CGI::Carpx::DebugScreen;
use CGI;
use CGI::Cookie;
use Config::Any;
use FindBin;
use SweetPea::Shell;
use SweetPea::Roots;
use Template;
use App;

=head1 NAME

SweetPea::Seeds - This module loads all other helper modulers and provides accessors to the calling module!

=head1 VERSION

Version 0.01

=cut

our $VERSION = '0.01';

sub new {
    my ($class, $base)  = @_;
    my $self            = bless {}, $class;
       
       #include sweetpea base class
       $self->{'.base'}                              = $base;
       
       #declare config stuff
       $self->{store}->{application}->{html_content} = [];
       $self->{store}->{application}->{content_type} = 'text/html';
       $self->{store}->{application}->{path}         = $FindBin::Bin;
       
       #load core modules
       $self->{'.roots'}                             = SweetPea::Roots->new($self);
       
       #load cpan/other modules
       $self->{'.app'}                               = App->new($self);
       
       #setup runtime env
       $self->{'.shell'}                             = SweetPea::Shell->new($self);
       
       #add application object to debugger watchlist hash for debugger output
       #CGI::Carpx::DebugScreen->add_watchlist( 'Application Store' => Data::Dumper::Dumper($self->{store}) );
       
    return $self;
}

=head1 SYNOPSIS

    use SweetPea::Seeds;

    my $s = SweetPea::Seeds->new(SweetPea->new);
    $s->params->{foo};

=head1 EXPORT

A list of functions that can be exported.  You can delete this section
if you don't export anything, such as for a purely object-oriented module.

=head1 FUNCTIONS

=head2 start

=cut

sub start
{
    my $self = shift;
    
    #handle session
    $self->session->expire('+1h'); #set session expiration
    $self->cookie( -name => $self->session->name, -value => $self->session->id );
    
    #print http header
    print "HTTP/1.0 200 OK\r\n" if $self->application->{http_server}->{on};
    print $self->cgi->header(-type => $self->application->{content_type}, -status => 200, -cookie => $self->cookies );
}

=head2 finish

=cut

sub finish
{
    my $self = shift;
    
    #print gathered html unless a template has been stored
    my $html = $self->html;
    if ( $html && !$self->store->{template} ) { print "$_\n" foreach (@{$html}) }
    
    #print template if a template has been stored
    if ( $self->template )
    {
        #print processed template - Note! template(s) overwrites any other store output
        $self->template->process( $self->store->{template}, { s => $self, c => $self->config->{'.conf'} } ) if $self->store->{template};
        croak ucfirst($self->template->error()->[0]) . " error, " . $self->template->error()->[1] if $self->template->error();
    }
    
    #commit session changes
    $self->session->flush();
    exit unless $self->application->{http_server}->{on};
    #die if $self->application->{http_server}->{on}; #hack to keep the http server running (not quite sure why this works)
}

=head2 forward

=cut

sub forward
{
    my ($self, $path) = @_;
    #get actions
    my %dispatch = %{$self->roots->load_path_and_actions()};
    #run requested routines
    $dispatch{"$path/begin"}->($self) if exists $dispatch{"$path/begin"};
    $dispatch{"$path"}->($self) if exists $dispatch{"$path"};
    $dispatch{"$path/end"}->($self) if exists $dispatch{"$path/end"};
}

=head2 break

=cut

sub break
{
    my ($self, $path) = @_;
    $self->forward($path);
    $self->start();
    $self->finish();
}

=head2 redirect

=cut

sub redirect
{
    my ($self, $path) = @_;
    print "Status: 302 Moved\nLocation: $path \n\n";
    exit;
}

=head2 store

=cut

sub store
{
    my $self = shift;
    return $self->{store};
}

=head2 application

=cut

sub application
{
    my $self = shift;
    return $self->{store}->{application};
}

=head2 uri

=cut

sub url
{
    my $self = shift;
    return $self->{store}->{application}->{'url'};
}

=head2 base

=cut

sub base
{
    my $self = shift;
    return $self->{'.base'};
}

=head2 conf

=cut

sub conf
{
    my $self = shift;
    return $self->config->{'.conf'};
}

=heads cookies

Returns a list of cookies set throughout the duration of the request

=cut

sub cookies
{
    my $self = shift;
    return ref $self->{store}->{application}->{cookie_data} eq "ARRAY" ? @{$self->{store}->{application}->{cookie_data}} : ();
}

=head2 html

=cut

sub html
{
    my ($self, @html) = @_;
    if ( @html )
    {
        my @existing_html = $self->{store}->{application}->{html_content} ? @{$self->{store}->{application}->{html_content}} : ();
        push @existing_html, @html;
        $self->{store}->{application}->{html_content} = \@existing_html;
        return;
    }
    else
    {
        if ( $self->{store}->{application}->{html_content} )
        {
            my @content = @{$self->{store}->{application}->{html_content}};
               $self->{store}->{application}->{html_content} = [];
            return \@content;
        }
    }
}

=head1 MODULE ACCESSORS

=head2 plug

This function creates accessors for third party (non-core) modules

=cut

sub plug
{
    my ($self, $name, $init) = @_;
    if ($name && $init)
    {
        no warnings 'redefine';
        no strict 'refs';
        my $routine = "SweetPea::Seeds::$name";
        if ( ref $init eq "CODE" )
        {
            *{$routine} = sub { $self->{".$name"} = $init->(@_) unless $self->{".$name"}; return $self->{".$name"} };
        }
        else
        {
            *{$routine} = sub { $self->{".$name"} = $init unless $self->{".$name"}; return $self->{".$name"} };
        }
    }
}

=head2 cookie

=cut

#sub cookie
#{
#    my ($self, @params) = @_;
#    return $self->cgi->cookie(@params);
#}

=head2 roots

=cut

sub roots
{
    my $self = shift;
    return $self->{'.roots'};
}

=head2 shell

=cut

sub shell
{
    my $self = shift;
    return $self->{'.shell'};
}

=head2 cgi

=cut

sub cgi
{
    my $self = shift;
    return $self->{'.cgi'};
}

=head2 debug

=cut

sub debug
{
    my ($self, $message, $die) = @_;
    my ($package, $filename, $line) = caller(0);
    my @msgs = $self->{'.debug'} ? @{$self->{'.debug'}} : ();
    push @msgs, $message;
    $self->{'.debug'} = \@msgs;
    warn "* $#msgs. $message at $package ($filename) on line $line\n" unless $die;
    die "* $#msgs. $message at $package ($filename) on line $line\n" if $die;
}

=head1 AUTHOR

Al Newkirk, C<< <al.newkirk at awnstudio.com> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-sweetpea-Seeds at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=SweetPea-Seeds>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc SweetPea::Seeds


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=SweetPea-Seeds>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/SweetPea-Seeds>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/SweetPea-Seeds>

=item * Search CPAN

L<http://search.cpan.org/dist/SweetPea-Seeds/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 COPYRIGHT & LICENSE

Copyright 2009 Al Newkirk, all rights reserved.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.


=cut

1; # End of SweetPea::Seeds
